/*
 * @Author: dgflash
 * @Date: 2022-06-28 17:57:23
 * @LastEditors: dgflash
 * @LastEditTime: 2022-09-20 10:29:15
 */

import chalk from "chalk";
import { HttpClient, HttpServer, HttpServerOptions, PrefixLogger, WsClient, WsServer, WsServerOptions } from "tsrpc";

//import { serviceProto as AccountServiceProto, ServiceType as AccountServiceType } from "../../tsrpc/shared/protocols/AccountServiceProto";
import { serviceProto as HallServiceProto, ServiceType as HallServiceType } from "../../tsrpc/shared/protocols/HallServiceProto";
import { serviceProto as RoomServiceProto, ServiceType as RoomServiceType } from "../../tsrpc/shared/protocols/RoomServiceProto";

import { Config } from "../config/Config";
import { CommonUtil } from "./CommonUtil";
import { ShareConfig } from "../config/ShareConfig";
import { Security } from "./Security";
import { BaseConf } from "../../tsrpc/shared/protocols/base";

/** TSRPC 客户端、服务器对象工厂 */
export class CommonFactory {

    // /** 创建 Websocket 房间服务器 */
    static createWssRoom() {
        let options: Partial<WsServerOptions<RoomServiceType>> = {
            port: parseInt(Config.room.port),
            logMsg: Config.room.logMsg,
            json: ShareConfig.json,
            wss: CommonUtil.getCertificate()
        }

        let wss = new WsServer(RoomServiceProto, options);
        this.flowServerMsg(wss);
        this.checkAuth(wss);
        //account.checkAuth(wss);                   // 检查客户端身份

        return wss;
    }
    //检查客户端权限
    /** 检查服务器身份 */
    static checkAuth(server: HttpServer | WsServer) {
        server.flows.preApiCallFlow.push(async call => {
            let conf: BaseConf | undefined = call.service.conf;

            // 执行 API 接口实现之前通过令牌获取当前用户信息
            // let req = call.req as BaseRequest;
            // if (req.__ssoToken) {
            //     call.user = this.parseSSO(req.__ssoToken);
            // }

            // 验证请求客户端地址是否在白名单列表中
            if (conf?.needCheckAddress && (Config.ips as any)[call.conn.ip] == undefined) {
                await call.error('没有访问权限', { code: 'NEED_AUTHORITY' });
                return null;
            }
            // 玩家必须登录才可以访问服务
            // else if (conf?.needLogin && !call.user) {
            //     await call.error('登录后获取访问权限', { code: 'NEED_LOGIN' });
            //     return null;
            // }

            return call;
        });
    }

    /** 创建匹配服务器的 Http 客户端连接 */
    static createHcHall() {
        let url = `${ShareConfig.https ? "https" : "http"}://${Config.hall.ip}:${Config.hall.port}/`;
        let hc = new HttpClient(HallServiceProto, { server: url });
        this.flowClientApi(hc);

        return hc;
    }
    // // /** HTTP 客户端协议数据加密、解密 */
    private static flowClientApi(hc: HttpClient<HallServiceType>) {
        if (!ShareConfig.security) return;

        hc.flows.preSendDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.encrypt(v.data);
            }
            return v;
        });

        // 在处理接收到的数据之前，通常要进行加密/解密
        hc.flows.preRecvDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.decrypt(v.data);
            }
            return v;
        });

    }

    // /** WebSocket 服务器协议数据加密、解密 */
    private static flowServerMsg(wss: WsServer) {
        if (!ShareConfig.security) return;

        wss.flows.preSendMsgFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.encrypt(v.data);
            }
            return v;
        });

        // 在处理 MsgCall 之前
        wss.flows.preMsgCallFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.decrypt(v.data);
            }
            return v;
        });
    }
}